// BoomIndex.ts

import { _decorator, AudioClip, Component, EventTarget, resources, view, View } from 'cc';
const { ccclass, property } = _decorator;
import * as fgui from "fairygui-cc";
import PlayerCtrl from './ctrl/PlayerCtrl';
import { GameController, ResultData } from './manager/GameController';
import CardCtrl from './ctrl/CardCtrl';
import ProgressCtrl from './ctrl/ProgressCtrl';
import EventDefine from './config/EventDefine';
import ResultCtrl from './ctrl/ResultCtrl';
import ToastCtrl from './ctrl/ToastCtrl';
import TopCtrl from './ctrl/TopCtrl';
import lodash, { first } from 'lodash'

import uni from './utils/uni.js'
import { AudioManager } from './manager/AudioManager';

@ccclass("BoomIndex")
export default class BoomIndex extends Component {

    private _view: fgui.GComponent = null;
    private eventTarget: EventTarget = new EventTarget();
    private audioManager: AudioManager = null;

    private _roundController: fgui.Controller = null;
    private _playerListShow: fgui.Controller = null;
    private _boomLevelShow: fgui.Controller = null;
    private _upEnergyTipShow: fgui.Controller = null;
    private _toastShow: fgui.Controller = null;
    private _countDownShow: fgui.Controller = null;
    private _selectCardShow: fgui.Controller = null;
    private _progressShow: fgui.Controller = null;
    private _resultlPage: fgui.Controller = null;
    private _loadingShow: fgui.Controller = null;

    private _roundStartEndAni: fgui.GLoader3D = null;

    private _roundAniController: fgui.Controller = null;

    //顶部显示及控制器
    private _crystalLabel: fgui.GTextField = null;
    private _gameCountdownLabel: fgui.GComponent = null;

    private _needCrystalLebel: fgui.GTextField = null;
    private _waitCountdownLabel: fgui.GComponent = null;
    private _willStartCountdownLabel: fgui.GComponent = null;

    //游戏控制抽象类
    private _topCtrl: TopCtrl = null;
    private _playerCtrl: PlayerCtrl = null;
    private _cardCtrl: CardCtrl = null;
    private _progressCtrl: ProgressCtrl = null;
    private _resultCtrl: ResultCtrl = null;
    private _toastCtrl: ToastCtrl = null;

    private _bottomButton: fgui.GComponent = null;
    private _musicButton: fgui.GComponent = null;
    private _bottomButtonController: fgui.Controller = null;
    private _progressWidget: fgui.GComponent = null;

    private _bossGLoader: fgui.GLoader3D = null;

    private remainingTime: number = 3; // 剩余时间（单位：秒）

    private throttledButtonHandler: Function;


    onLoad() {
        fgui.UIPackage.loadPackage("UI/GameBoom", this.onUILoaded.bind(this));
    }

    onUILoaded() {

        fgui.UIPackage.addPackage('UI/GameBoom')

        this._view = fgui.UIPackage.createObject("GameBoom", "Index").asCom;
        if (!this._view) {
            console.error("创建 UI 失败");
            return;
        }
        else {
            this._view.makeFullScreen()
            uni.postMessage({
                data: {
                    type: 'gameLoaded'
                }
            });
        }

        fgui.GRoot.inst.addChild(this._view);
        this.initControllersAndWidget();
        this.initGameCtrl()
        this.initEvents()
        GameController.Instance.onConnectToNewGame(false)
    }

    private onGameHide() {
        this.gameReset()
        this._cardCtrl.reset()
        GameController.Instance.closeWebSocket()

        this.audioManager.setMenu(false);
        this.audioManager.pauseBgm();
    }

    private initControllersAndWidget() {
        // 创建控制器名称与属性的映射关系
        const controllerMap = [
            { prop: "_roundController", name: "huihe" },
            { prop: "_playerListShow", name: "gamePosition" },
            { prop: "_boomLevelShow", name: "zhadan_sl" },
            { prop: "_upEnergyTipShow", name: "nengliang_zj" },
            { prop: "_toastShow", name: "tos" },
            { prop: "_countDownShow", name: "daojishi" },
            { prop: "_selectCardShow", name: "xuankapai" },
            { prop: "_progressShow", name: "nengliang" },
            { prop: "_resultlPage", name: "jieguo" },
            { prop: "_loadingShow", name: "loading" }
        ];

        // 通过循环统一设置
        controllerMap.forEach(({ prop, name }) => {
            this[prop] = this._view.getController(name);
        });

        this._crystalLabel = this._view.getChild('n7').asCom.getChild('n2', fgui.GTextField)

        this._bottomButton = this._view.getChild("n17").asCom
        this._progressWidget = this._view.getChild("n39").asCom
        this._bottomButtonController = this._bottomButton.getController("c1")

        this._gameCountdownLabel = this._view.getChild('n21').asCom.getChild('n1').asCom
        this._needCrystalLebel = this._bottomButton.getChild('n6', fgui.GTextField)
        this._waitCountdownLabel = this._bottomButton.asCom.getChild('n10').asCom
        this._willStartCountdownLabel = this._bottomButton.asCom.getChild('n14').asCom

        this.throttledButtonHandler = lodash.throttle(() => {
            this.buttonEvent();
        }, 1000);

        this._bottomButton.onClick(this.throttledButtonHandler, this)
        this._musicButton = this._view.getChild('n58').asCom
        let musicController = this._musicButton.getController('c1')
        this._musicButton.onClick(() => {
            if (musicController.selectedIndex == 0) {
                this.audioManager.setMenu(false);
                musicController.selectedIndex = 1;
            }
            else {
                this.audioManager.setMenu(true);
                musicController.selectedIndex = 0;
            }
        })

        const recordsButton = this._view.getChild("n52").asCom;
        recordsButton.onClick(this.navitgateToRecords, this)

        const ruleButton = this._view.getChild("n51").asCom;
        ruleButton.onClick(this.navitgateToRule, this)

        let backButton = this._view.getChild("n12").asCom;
        backButton.onClick(this.backEvent, this)
        backButton.y = Math.max(100, this._view.height * 0.072);

        this._bottomButton.y = this._view.height - 200
        this._progressWidget.y = this._view.height - 200

        this._view.getChild('n1').asCom.y = this._view.height - 354

        const bgView = this._view.getChild('n0').asCom;

        bgView.width = view.getVisibleSize().width;
        bgView.x = 0; bgView.y = 0;

        const titleView = this._view.getChild('n4').asCom;
        titleView.x = 20;

        const roundStartEndView = this._view.getChild('n41').asCom;
        this._roundStartEndAni = roundStartEndView.getChild('n4', fgui.GLoader3D);

        const roundAni = this._view.getChild('n78').asCom;
        this._roundAniController = roundAni.getController('c1')

        this._bossGLoader = this._view.getChild('n88', fgui.GLoader3D);
    }

    initGameCtrl() {
        this.audioManager = AudioManager.Instance;
        resources.load('sounds/bgm', (error, data: AudioClip) => {
            this.audioManager.playBgm(data, 1.0);
        })
        const topWidget = this._view.getChild("n8").asCom
        topWidget.getChild("n9").asCom.onClick(this.selectBoomEvent, this)
        const areaController = topWidget.getChild("n9").asCom.getController('jiebie')

        this._topCtrl = new TopCtrl(topWidget);

        ['n8', 'n9', 'n10'].forEach((item, idx) => {
            this._view.getChild('n9').asCom.getChild(item).onClick(() => {
                if (idx != 0) {
                    this._toastCtrl.showToast(3, 2);
                }
                else {
                    GameController.Instance.gameAraeIndex = idx;
                    areaController.selectedIndex = idx;
                    this._needCrystalLebel.text = GameController.Instance.gameAreaArray[idx].crystal.toString();
                }
                this._boomLevelShow.selectedIndex = 0;
            })
        })

        const playerBox = this._view.getChild("n13").asCom
        const playerDisplayList = this._view.getChild("n6").asCom
        this._playerCtrl = new PlayerCtrl(this._view, playerBox, playerDisplayList, this._playerListShow)
        this._playerCtrl.refreshToastHandle = () => this._toastCtrl.showToast(2, 2);

        const cardNode = this._view.getChild("n23").asCom;
        this._cardCtrl = new CardCtrl(cardNode, this._selectCardShow)
        this._cardCtrl.cardSelectedHandle = (cardInfo) => {
            Promise.resolve().then(() => {
                this.cardSelectedEvent(cardInfo);
            })
        }

        const progress = this._view.getChild("n39").asCom;
        const roundUpEnergyLabel = this._view.getChild('n14').asCom.getChild('n1').asCom
        this._progressCtrl = new ProgressCtrl(progress, this._upEnergyTipShow, roundUpEnergyLabel);

        const winNode = this._view.getChild("n44").asCom;
        const failNode = this._view.getChild("n47").asCom;
        this._resultCtrl = new ResultCtrl(winNode, failNode, this._resultlPage, this._view.height - 240)
        this._resultCtrl.resetHanlde = () => {
            this.gameReset()
            this._playerCtrl.creatorRandomSelectorAndStart();
        }

        const toast = this._view.getChild('n20').asCom;
        this._toastCtrl = new ToastCtrl(toast, this._toastShow)
    }

    initEvents() {

        this.eventTarget = GameController.Instance.eventTarget;

        this.eventTarget.on(EventDefine.wsOpen, () => {
            GameController.Instance.onConnectToNewGame(false)
            this._loadingShow.selectedIndex = 1;
        })

        this.eventTarget.on(EventDefine.wsClose, (event) => {
            if (event.reason === 'Bye') {
                console.log('Token无效或超时')
                uni.navigateBack({ delta: 1 })
            }
        })

        this.eventTarget.on(EventDefine.gameShow, () => {
            console.log('gameshow')
            this.audioManager.setMenu(true);
            this.audioManager.resumeBgm();
            this._view.makeFullScreen()

        }, this)

        this.eventTarget.on(EventDefine.gameHide, () => {
            this.onGameHide()
        }, this)

        this.eventTarget.on(EventDefine.GameConnectSuccess, () => {
            Promise.resolve().then(() => {
                this.gameConnectSuccess()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameUpdateNormalBetArea, () => {
            Promise.resolve().then(() => {
                this._loadingShow.selectedIndex = 0;
                this._needCrystalLebel.text = `${GameController.Instance.gameAreaArray[GameController.Instance.gameAraeIndex].crystal}`

                if (GameController.Instance.gameAreaArray[GameController.Instance.gameAraeIndex].status == '1') {
                    this._bottomButtonController.selectedIndex = 3;
                };
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRunning, () => {
            Promise.resolve().then(() => {
                this.gameRunning()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRunningSelected, () => {
            Promise.resolve().then(() => {
                this._toastCtrl.showRoundWaitingToast();
            })
        }, this)

        this.eventTarget.on(EventDefine.UpdateCrystal, (crystal) => {
            this._crystalLabel.text = `${crystal}`
        }, this)

        this.eventTarget.on(EventDefine.UpdateGamePlayerNums, (nums) => {
            Promise.resolve().then(() => {
                this._topCtrl.updateGamePlayerNums(nums)
                this._playerCtrl.gameUpdateReadyPlayersQueue()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameReady, (remainingTime) => {
            this.remainingTime = remainingTime;
            Promise.resolve().then(() => {
                this.gameReady()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameTransfer, () => {
            Promise.resolve().then(() => {

            })
        }, this)

        this.eventTarget.on(EventDefine.GameCrystalNotEnough, () => {
            Promise.resolve().then(() => {
                this._toastCtrl.showToast(5, 1)
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRemake, () => {
            Promise.resolve().then(() => {
                this.gameRemake()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameUpdatePlayersInfo, (infoArray) => {
            Promise.resolve().then(() => {
                this._playerCtrl.updatePlayerInfo(infoArray)
                this.scheduleOnce(() => {
                    this._progressCtrl.roundUpdateEvent()
                }, 0.2)
            })
        }, this)

        this.eventTarget.on(EventDefine.GameStart, () => {
            Promise.resolve().then(() => {
                this.gameStart()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRoundRun, () => {
            Promise.resolve().then(() => {
                this.gameRoundChange()
                this._toastCtrl.hideToast()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRoundCard, (cardArray) => {
            Promise.resolve().then(() => {
                this.addCards(cardArray)
            })
        }, this)

        this.eventTarget.on(EventDefine.GamePlayerSelectedCard, (card) => {
            Promise.resolve().then(() => {
                this._cardCtrl.seletedCard(card)
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRoundEnd, () => {
            Promise.resolve().then(() => {
                this._toastCtrl.showRoundReadyToast()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameRoundCountDown, (remain) => {
            Promise.resolve().then(() => {
                this.gameRoundUpdateCountdown(remain);
            })
        }, this)

        this.eventTarget.on(EventDefine.GameEnd, () => {
            Promise.resolve().then(() => {
                this.gameEnd()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameMonsterBoom, () => {
            Promise.resolve().then(() => {
                this.monsterBoomEvent()
            })
        }, this)

        this.eventTarget.on(EventDefine.GameResultEvent, () => {
            Promise.resolve().then(() => {
                this.scheduleOnce(() => {
                    this._playerCtrl.monsterBoom()
                }, 2)
            })
        }, this)

        this.eventTarget.on(EventDefine.GameServicingDown, () => {
            Promise.resolve().then(() => {
               this._bottomButtonController.selectedIndex = 3;
            })
        }, this)

        //
        this.eventTarget.on(EventDefine.GameAutoStart, (remain) => {
            Promise.resolve().then(() => {
                this.gameAutoStart(remain)
            })
        }, this)

        this.eventTarget.on(EventDefine.GameSelectedCardUpdate, () => {
            Promise.resolve().then(() => {
                this.scheduleOnce(() => {
                    this._progressCtrl.updateInfo()
                }, 2.2)
            })
        })
    }

    private buttonEvent() {
        if (this._bottomButtonController.selectedIndex == 0 && !this._playerCtrl.refreshing) {
            GameController.Instance.onConnectToNewGame(true);
        }
    }

    selectBoomEvent() {
        if (this._boomLevelShow.selectedIndex == 0) {
            this._boomLevelShow.setSelectedIndex(1)
        }
        else {
            this._boomLevelShow.setSelectedIndex(0)
        }
    }

    private gameReady() {
        this._bottomButtonController.setSelectedIndex(1)
        this.updateWaitCountdown();
        this.schedule(this.updateWaitCountdown, 1);
        this._playerCtrl.gameReady();
    }

    private gameAutoStart(remain) {
        this.remainingTime = remain;
        this._bottomButtonController.setSelectedIndex(2)
        this.updateWaitCountdown();
        this.schedule(this.updateWaitCountdown, 1);
    }

    //等待游戏开始定时器
    private updateWaitCountdown() {

        if (this.remainingTime < 0) {
            this.remainingTime = 0;
        }
        if (this._bottomButtonController.selectedIndex == 1) {
            this._waitCountdownLabel.text = labelTimeFormat(this.remainingTime);
        }
        else if (this._bottomButtonController.selectedIndex == 2) {
            this._willStartCountdownLabel.text = labelTimeFormat(this.remainingTime);
        }
        else {
            return;
        }

        this.remainingTime--;

        // 倒计时结束处理
        if (this.remainingTime < 0) {
            this.unschedule(this.updateWaitCountdown); // 停止定时器
        }

        //格式化时间
        function labelTimeFormat(remain) {
            const seconds = remain < 10
                ? `0${remain}`
                : `${remain}`;
            return `00:${seconds}`;
        }
    }

    gameConnectSuccess() {
        this._progressCtrl.updateInfo()
        if (GameController.Instance.gameResultData == null) {
            this._playerCtrl.creatorRandomSelectorAndStart()
        }
    }

    gameRunning() {
        this._progressShow.setSelectedIndex(1);
        this._topCtrl.gameStart();
        this._topCtrl.gameRoundChange()

        this.scheduleOnce(() => {
            this._progressCtrl.updateInfo()
            this._playerCtrl.gameReConnect()
        }, 0.1)
    }

    gameStart() {
        // 停止游戏准备定时器
        this.unschedule(this.updateWaitCountdown);
        this._toastCtrl.showToast(2, 2);
        this._progressShow.setSelectedIndex(1);
        this._topCtrl.gameStart();
        this._playerCtrl.gameStart();
    }

    gameRoundChange() {
        let gameRound = GameController.Instance.gameRound

        if (gameRound == 1) {
            this.roundChangeAnimation(1)
            this._roundStartEndAni.animationName = 'MovieClip7'
        }

        else {
            this.roundChangeAnimation(2)
            this._roundAniController.selectedIndex = gameRound - 1;
        }

        this._topCtrl.gameRoundChange()
    }

    addCards(cardArray: Array<cardInfo>) {
        if (cardArray.length === 0) {
            this._toastCtrl.showRoundWaitingToast()
        }
        else {
            this._cardCtrl.updateCardInfo(cardArray)
        }
    }

    gameEnd() {
        this.roundChangeAnimation(1)
        this._roundStartEndAni.animationName = 'MovieClip8'

        this._topCtrl.gameEnd()
        this._toastCtrl.hideToast();
    }

    private gameRemake() {
        this._toastCtrl.showToast(4, 2);
        this.unschedule(this.updateWaitCountdown);
        this._playerCtrl.reset();
        this._playerCtrl.creatorRandomSelectorAndStart()
        this._bottomButtonController.setSelectedIndex(0)
        this._topCtrl.reset()
    }

    private gameReset() {
        this._playerCtrl.reset();

        this._topCtrl.reset()
        this._bottomButtonController.setSelectedIndex(0)
        this._progressShow.setSelectedIndex(0);
        this._progressCtrl.reset()
        this._toastCtrl.hideToast()
        GameController.Instance.reset()
    }

    private monsterBoomEvent() {

        this.audioManager.playEffectWithName('boom')
        const playerBoxAni = this._playerCtrl.playersBox.getController('c1')
        this.scheduleOnce(() => {
            playerBoxAni.setSelectedIndex(1);
        }, 2)


        this._bossGLoader.animationName = "die"
        this.scheduleOnce(() => {
            this._bossGLoader.visible = false;
        }, 3.75)

        this.scheduleOnce(() => {
            this._resultCtrl.showResult()
            this._bossGLoader.visible = true;
            this._bossGLoader.animationName = "idle"
            playerBoxAni.setSelectedIndex(0);
        }, 4.5)
    }

    private roundChangeAnimation(round) {
        this._roundController.setSelectedIndex(round);
        this.scheduleOnce(() => {
            this._roundController.setSelectedIndex(0)
        }, 1.5);
    }

    private cardSelectedEvent(cardInfo: cardInfo) {
        // this._playerCtrl.updateSelfEnergy();

        console.log(`[${new Date().toLocaleTimeString()}] + cardSelectedEvent`, cardInfo.shield)

        this.resetRoundCountdown();
        this._progressCtrl.updataEnergy(parseInt(cardInfo.shield));
        this.progressUpdateEnergyAni()

        this._toastCtrl.showRoundWaitingToast()
    }

    private progressUpdateEnergyAni() {
        this._progressCtrl.aniController.selectedIndex = 1;
        this.scheduleOnce(() => {
            this._progressCtrl.aniController.setSelectedIndex(0);
        }, 1)
    }

    private roundRemainingTime = 15;

    private gameRoundUpdateCountdown(remain) {
        if (GameController.Instance.currentEnergy > 30) return;
        this.roundRemainingTime = remain
        this.updateRoundCountdown();
        this.schedule(this.updateRoundCountdown, 1);
        this._countDownShow.setSelectedIndex(1);
    }

    //游戏回合定时器
    private updateRoundCountdown() {
        this._gameCountdownLabel.text = `${this.roundRemainingTime}`;
        this.roundRemainingTime--;
        if (this.roundRemainingTime < 0) {
            this.resetRoundCountdown();
        }
    }

    //重置回合定时器
    private resetRoundCountdown() {
        this.roundRemainingTime = 15
        this._gameCountdownLabel.text = `${this.roundRemainingTime}`;
        this._countDownShow.setSelectedIndex(0);
        this.unschedule(this.updateRoundCountdown); // 停止定时器
    }

    //返回事件
    private backEvent() {
        console.log('back')
        uni.navigateBack();
    }

    private navitgateToRecords() {
        console.log('navitgateToRecords =')
        uni.navigateTo({
            url: '/pages/paly/recordZd'
        });
    }

    private navitgateToRule() {
        console.log('navitgateToRule =')
        uni.navigateTo({
            url: '/pages/paly/ruleZd'
        });
    }
}